/*
*  SkyALUTDecoder.cpp
*  
*
*  Created by Alexander Trutchenko on 11/02/12.
*  Copyright 2012 Free Team. All rights reserved.
*
*/

#include "SkyALUTDecoder.h"

#include "SkyFile.h"
#include "SkyUtils.h"
#include "SkyAssert.h"
#include "SkyOpenALBuffer.h"

#include "alut.h"

#include <algorithm>

namespace sky {

////////////////////////////////////////////////////////
//
/** SkyALUTStaticDecoder
*  
*/
////////////////////////////////////////////////////////

SkyALUTStaticDecoder::SkyALUTStaticDecoder()
{
	if (!_isValid)
		false;

	ALboolean res = alutInitWithoutContext(NULL, NULL);
	ALenum err = alutGetError();
	if (res != AL_TRUE || !(err == ALUT_ERROR_NO_ERROR || err == ALUT_ERROR_INVALID_OPERATION))
		_isValid = false;
	
}
SkyALUTStaticDecoder::~SkyALUTStaticDecoder()
{
	ALboolean res = alutExit();
	ALenum err = alutGetError();
	SkyAssert(res == AL_TRUE && err == ALUT_ERROR_NO_ERROR, "SkyALUTStaticDecoder::~SkyALUTStaticDecoder(): wrong exit!");
}

ALuint SkyALUTStaticDecoder::getBufferIDFromFileData(const SkyFileData& fileData) const
{
	return alutCreateBufferFromFileImage(fileData.data(), fileData.size());
}

SkyMemoryWrapper* SkyALUTStaticDecoder::getPCMDataFromFileData(const SkyFileData& fileData, SkyBufferHeader& header) const
{
	ALfloat frequency = 0.f;
	ALvoid *decodedData = alutLoadMemoryFromFileImage (fileData.data(), fileData.size(), &header.format, &header.decodedSize, &frequency);
	header.frequency = (ALsizei)frequency;
	SkyMemoryWrapper* wrapper = new SkyCArrayWrapper<ALvoid>(decodedData, header.decodedSize); 
	return wrapper;
}

void SkyALUTStaticDecoder::onSetCurrentContext()
{
	if (!_isValid)
		return;

	unsigned int cursor = 0;
	std::vector<std::string> extentions;
	ALenum err = alutGetError();
	const char* mimeTypes = alutGetMIMETypes(ALUT_LOADER_BUFFER);
	if (mimeTypes != NULL)
	{
		std::string str = mimeTypes;
		while (cursor < str.length())
		{
			unsigned int nextSeparator = str.find_first_of(',', cursor);
			getFileExtFromMimeType(str.substr(cursor, nextSeparator - cursor), extentions);
			if (nextSeparator > str.length())
				break;
			cursor = nextSeparator + 1;
		}
	}
	else
	{
		ALenum err = alutGetError();
		const char* errc = alutGetErrorString (err);
		SkyAssert(false, errc);
	}

	cursor = 0;
	err = alutGetError();
	mimeTypes = alutGetMIMETypes (ALUT_LOADER_MEMORY);
	if (mimeTypes != NULL)
	{
		std::string str = mimeTypes;
		while (cursor < str.length())
		{
			unsigned int nextSeparator = str.find_first_of(',', cursor);
			getFileExtFromMimeType(str.substr(cursor, nextSeparator - cursor), extentions);
			if (nextSeparator > str.length())
				break;
			cursor = nextSeparator + 1;
		}
	}
	else
	{
		ALenum err = alutGetError();
		const char* errc = alutGetErrorString (err);
		SkyAssert(false, errc);
	}

	sort(extentions.begin(), extentions.end());
	std::vector<std::string>::const_iterator itEnd = unique(extentions.begin(), extentions.end());
	for (std::vector<std::string>::const_iterator it = extentions.begin(); it != itEnd; ++it)
		_extentions.insert(*it);
}

void SkyALUTStaticDecoder::onClearCurrentContext() 
{
	if (!_isValid)
		return;
	_extentions.clear();
}

} // namespace sky
